package com.aaa.gs.config;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.log4j.Log4j2;

import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @ fileName:MyCustomRule
 * @ description:
 * @ author:zhz
 * @ createTime:2023/6/8 14:29
 * @ version:1.0.0
 */
@Log4j2
public class MyCustomRule  extends AbstractLoadBalancerRule {

    public MyCustomRule() {
    }

    /**
     * 使用算法选择服务器
     * @param lb   所有参与负载均衡的服务接口对象
     * @param key
     * @return
     */
    @SuppressWarnings("all")
    public Server choose(ILoadBalancer lb, Object key) {
        //int i = 0;
        if (lb == null) {
            return null;
        } else {

           log.info("lb-----开始:"+lb+"----------结束！");
            Server server = null;

            /**
             * 死循环，从参与负载均衡的服务器选择一个出来
             */
            while(server == null) {
                //判断线程是否中断   无论任何原因出现线程中断
                if (Thread.interrupted()) {
                    return null;
                }
                //Reachable 可达
                //获取在线（正常）服务
                List<Server> upList = lb.getReachableServers();
                log.info("upList-在线服务器列表："+upList);
                //获取所有服务器
                List<Server> allList = lb.getAllServers();
                log.info("allList-所有服务列表："+allList);
                //获取所有服务的个数
                int serverCount = allList.size();
                log.info("serverCount-所有服务的个数："+serverCount);
                //再次判断服务是否正常
                if (serverCount == 0) {
                    return null;
                }
                //随机算法的核心  从所有服务器数量，随机一个数字出来  目前3
                int index = this.chooseRandomInt(serverCount);
                log.info("随机服务的索引为："+index); // [0-2]
                //根据下标获取服务
                server = (Server)upList.get(index);
                log.info("被选择的服务是："+server);
                //再次判断服务是否为null  因为时时刻刻服务都可能宕机
                if (server == null) {
                    //当前线程让出CPU，让其他线程执行
                    Thread.yield();
                } else {
                    //再次判断服务是否存活
                    if (server.isAlive()) {
                        return server;
                    }

                    server = null;
                    Thread.yield();
                }
            }

            return server;
        }
    }

    /**
     * 随机数
     * @param serverCount
     * @return
     */
    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }

    public Server choose(Object key) {
        return this.choose(this.getLoadBalancer(), key);
    }

    public void initWithNiwsConfig(IClientConfig clientConfig) {
    }

    public static void main(String[] args) {
        int serverCount = 10;
        Random random=new Random();
        while(true) {
           // int i = random.nextInt(serverCount); //[0-(serverConnt-1)]
            int i1 = ThreadLocalRandom.current().nextInt(serverCount);
            System.out.println(i1);
        }
    }
}
